package com.ly.lypopupwindowdemo.views;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import com.ly.lypopupwindowdemo.R;
import com.ly.lypopupwindowdemo.util.PxUtils;

/**
 * Created by liying on 2017/6/8.
 * 圆形进度
 * 1.首先分析需求，我们的圆形进度总共分为三层，
 * 最底层是一个大园形，作为底色。
 * 第二层是一个扇形，大小跟底色一样，用来表示进度。
 * 第三层是一个小圆形，比背景色小，用于实现弧线的效果。
 * <p>
 * 来自：
 * http://www.open-open.com/lib/view/open1452576588605.html
 */

public class CirclePercentView extends View {
    //圆的半径
    private float mRadius;

    //色带的宽度
    private float mStripeWidth;
    //总体大小
    private int mHeight;
    private int mWidth;

    //动画位置百分比进度
    private int mCurPercent;

    //实际百分比进度
    private int mPercent;
    //圆心坐标
    private float x;
    private float y;

    //要画的弧度
    private int mEndAngle;

    //小圆的颜色
    private int mSmallColor;
    //大圆颜色
    private int mBigColor;

    /**
     * 饼状图的颜色
     */
    private int mArcColor;

    /**
     * 中间字体颜色
     */
    private int mTextColor;

    //中心百分比文字大小
    private float mCenterTextSize;

    public CirclePercentView(Context context) {
        this(context, null);
    }

    public CirclePercentView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    /**
     * getDimension和getDimensionPixelOffset功能差不多
     * 都是获取dimen的值
     * 都是获取某个dimen的值,如果是dp或sp的单位,将其乘以density,如果是px,则不乘;两个函数的区别是一个返回float,一个返回int.
     * getDimensionPixelSize则不管写的是dp还是sp还是px,都会乘以denstiy.
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public CirclePercentView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePercentView, defStyleAttr, 0);
        mStripeWidth = a.getDimension(R.styleable.CirclePercentView_stripeWidth, PxUtils.dpToPx(30, context));
        mCurPercent = a.getInteger(R.styleable.CirclePercentView_percent, 0);
        mSmallColor = a.getColor(R.styleable.CirclePercentView_smallColor, 0xffafb4db);
        mBigColor = a.getColor(R.styleable.CirclePercentView_bigColor, 0xff6950a1);
        mArcColor = a.getColor(R.styleable.CirclePercentView_arcColor, 0xffafb4db);
        mTextColor = a.getColor(R.styleable.CirclePercentView_textColor, Color.BLACK);
        mCenterTextSize = a.getDimensionPixelSize(R.styleable.CirclePercentView_centerTextSize, PxUtils.spToPx(20, context));
        mRadius = a.getDimensionPixelSize(R.styleable.CirclePercentView_radius, PxUtils.dpToPx(100, context));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取测量模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        //获取测量大小
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        /**
         * EXACTLY
         * 表示父视图希望子视图的大小应该由specSize的值来决定，
         * 系统会默认按照这个规则来设置子视图的大小，开发人员当然
         * 也可以按照自己的意愿设置成任意大小
         */
        if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
            mRadius = widthSize / 2;
            x = widthSize / 2;
            y = heightSize / 2;
            mWidth = widthSize;
            mHeight = heightSize;
        }

        /**
         * AT_MOST
         * 表示视图最多只能是specSize中指定的大小，开发人员
         * 应该尽可能小的去设置这个视图。
         */

        /**
         * UNSPECIFIED
         * 开发人员可以按照自己的意愿设置成任意的大小，没有任何的限制，这种情况少见，不太用到
         */

        if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            mWidth = (int) (mRadius * 2);
            mHeight = (int) (mRadius * 2);
            x = mRadius;
            y = mRadius;
        }
        setMeasuredDimension(mWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        /**
         * mCurPercent 0-100
         * mEndAngle   0-360
         * 所以每个percent对应3.6度
         * 已知percent  求度数
         * mCurPercent*3.6
         */
        mEndAngle = (int) (mCurPercent * 3.6);
        //绘制大圆
        Paint bigCirclePaint = new Paint();
        bigCirclePaint.setAntiAlias(true);
        bigCirclePaint.setColor(mBigColor);

        canvas.drawCircle(x, y, mRadius, bigCirclePaint);

        //饼状图
        Paint sectorPaint = new Paint();
        sectorPaint.setColor(mArcColor);
        sectorPaint.setAntiAlias(true);
        RectF rect = new RectF(0, 0, mWidth, mHeight);

        canvas.drawArc(rect, 270, mEndAngle, true, sectorPaint);

        //绘制小圆,颜色透明
        Paint smallCirclePaint = new Paint();
        smallCirclePaint.setAntiAlias(true);
        smallCirclePaint.setColor(mSmallColor);
        canvas.drawCircle(x, y, mRadius - mStripeWidth, smallCirclePaint);

        //绘制文本
        Paint textPaint = new Paint();
        String text = mCurPercent + "%";

        //////////////////
        //这两句注意应该先设置字的size再测量，否则如果先测量再设置字体的话会导致显示的时候有偏差
        textPaint.setTextSize(mCenterTextSize);
        float textLength = textPaint.measureText(text);
        ////////////////////

        textPaint.setColor(mTextColor);
        canvas.drawText(text, x - textLength / 2, y, textPaint);


    }

    //外部设置百分比数
    public void setPercent(int percent) {
        /**
         * 百分比超过100抛出异常
         */
        if (percent > 100) {
            throw new IllegalArgumentException("percent must less than 100!");
        }

        setCurPercent(percent);
    }

    //内部设置百分比 用于动画效果
    private void setCurPercent(int percent) {

        mPercent = percent;
        /**
         * 为了有动画的效果其实就是开启一个线程
         * 不断的重绘view,达到一个动画的效果
         */

        new Thread(new Runnable() {
            @Override
            public void run() {
                int sleepTime = 20;
                for (int i = 0; i < mPercent; i++) {
                    if (i % 20 == 0) {
                        sleepTime += 2;
                    }
                    try {
                        Thread.sleep(sleepTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    mCurPercent = i;
                    CirclePercentView.this.postInvalidate();
                }
            }

        }).start();
    }
}
